package musicIdentifyer.fingerPrint;
import musicIdentifyer.dataManager.DataManager;

import java.util.ArrayList;

/**
 * Created by Charles on 2016/10/29.
 */
public class FingerPrintReader {
    public static final double scaling = FFT.WINDOW_SIZE / 44100.0;

    public static final int N = 3;

    private ArrayList<int[]> constel_data = new ArrayList<>();
    private int id;

    /**
     * For songs about to add into DB
     * @param id
     */
    public FingerPrintReader(int id) {
        this.id = id;
    }

    /**
     * For songs about to be searched
     */
    public FingerPrintReader() {
        this.id = -1;
    }

    /**
     * Append a column of frequency peaks to the constellation map.
     * A frequency peak is a frequency value whose amplitude is the highest among
     * all frequencies in a frequency interval.
     *
     * @param freqDomain The frequency domain generated by FFT.
     */
    public void append(double[] freqDomain) {
        int[] freqPeaks = new int[N];
        //在下标为0-511中寻找能力最强的频率点
        //BFPRT算法求出前N大的数并放置于数组前N位
        BFPRT.BFPRT(freqDomain,5,500,N);
        //强制转换成int进行模糊匹配
       for (int i=0;i<N;i++)
       {
        freqPeaks[i]=(int)freqDomain[i+5];
       }
        //作为一帧添加进入list中
        constel_data.add(freqPeaks);
    }

    /**
     * Generate fingerprints using Combinational Hash.
     * For each frequency peak, generate 6 fingerprints with its 6 successors.
     *
     * @return
     */
    public ArrayList<ShazamHash> combineHash() {
        if (constel_data.size() < 3)
            throw new RuntimeException("Too few frequency peaks");
        ArrayList<ShazamHash> hashes = new ArrayList<>();
        for (int i = 0; i < constel_data.size() - 2; ++i) {
            for (int k = 0; k < N; ++k) {

                // "Combine" with all peak frequencies inside its next two frames.
                for (int j = 1; j <= 2; ++j) {
                    for (int kk = 0; kk < N; ++kk) {
                        ShazamHash hash = new ShazamHash();
                        hash.f1 = (short) constel_data.get(i)[k];
                        hash.f2 = (short) constel_data.get(i + j)[kk];
                        hash.dt = (short) j;
                        hash.offset = i;
                        hash.id = id;
                        hashes.add(hash);
                    }
                }
            }
        }
        return hashes;
    }
/*
    //select算法
    int partition(double[] data,int headId,int tailId)
    {
        int posSlow=headId-1;
        int posFast=headId;
        double swapNum=0;
        for (;posFast<tailId;posFast++)
        {
            if (data[posFast]>data[tailId])
            {
                posSlow++;
                swapNum = data[posFast];
                data[posFast] = data[posSlow];
                data[posSlow] = data[posFast];
            }
        }
        posSlow++;
        swapNum = data[tailId];
        data[tailId] = data[posSlow];
        data[posSlow] = data[tailId];
        return  posSlow;//返回主元位置
    }


    void select_algor(double[] data,int headId,int tailId)
    {
        if (headId<=tailId)//越界退出
        {
            return;
        }
        int midId=partition(data,headId,tailId);
        if (midId>N)
        {
            select_algor(data,headId,midId-1);//midID主元所在位置比该区域所有都小，不用再次排序
        }
    }
    */
   public static void main(String[] args)
   {

       double[] timeDoim = new double[10];//Test
       double[] freDoim = FFT.fft(timeDoim);//frequence

       //
       FingerPrintReader myFingerPrintReader = new FingerPrintReader(1);
       myFingerPrintReader.append(freDoim);
       ArrayList<ShazamHash> Hashmap = myFingerPrintReader.combineHash();

       //Save data
       DataManager myDataManager = new DataManager();
       myDataManager.saveHash(Hashmap);

   }
}

